package org.walkerljl.commons.dts;


import org.walkerljl.commons.exception.AppException;
import org.walkerljl.commons.log.Logger;
import org.walkerljl.commons.log.LoggerFactory;
import org.walkerljl.commons.util.ListUtils;

import java.util.List;

/**
 * DTS Manager
 *
 * @author lijunlin
 */
public class DtsManager {

    private static final Logger LOGGER = LoggerFactory.getLogger(DtsManager.class);
    private static final String MESSAGE_PREFIX = "DTS MANAGER ==>>";

    /**
     * Execute
     * @param executor
     * @param dtsParam
     * @return
     */
    public static DtsResult execute(DtsExecutor executor, DtsParam dtsParam) {
        return DtsManager.execute(executor, ListUtils.<DtsParam>newArrayList(dtsParam));
    }

    /**
     * Execute
     * @param executor
     * @param dtsParams
     * @return
     */
    public static DtsResult execute(DtsExecutor executor, List<DtsParam> dtsParams) {
        //prepare
        DtsResult result = executor.prepare(dtsParams);
        trace(result, "prepare");
        if (result.isFailure()) {
            return result;
        }

        //commit
        result = executor.commit(dtsParams);
        trace(result, "commit");
        if (result.isSuccess()) {
            return result;
        }

        //fail to commit, rollback
        DtsResult rollbackResult = executor.rollback(result.getCompletedParams());
        trace(rollbackResult, "rollback");
        return result;
    }

    /**
     * Rollback
     * @param executor
     * @param dtsParams
     * @return
     */
    public static DtsResult rollback(DtsExecutor executor, List<DtsParam> dtsParams) {
        DtsResult result = executor.rollback(dtsParams);
        trace(result, "rollback");
        return result;
    }

    /**
     * Trace
     * @param result
     * @param key
     */
    private static void trace(DtsResult result, String key) {
        if (!LOGGER.isDebugEnabled()) {
            return;
        }
        if (result.isSuccess()) {
            LOGGER.debug(String.format("%s success to %s", MESSAGE_PREFIX, key));
        } else {
            LOGGER.debug(String.format("%s failure to %s, message:%s", MESSAGE_PREFIX,
                    key, result.getMessage(), result.getThrowable()));
        }
    }
    
    /**
     * Assert result
     *
     * @param dtsResult
     */
    public static void assertResult(DtsResult dtsResult){
    	if (dtsResult.isFailure()) {
            if (dtsResult.getThrowable() == null) {
                throw new AppException("Fail to execute DtsHandler");
            } else {
                throw new AppException(dtsResult.getThrowable());
            }
        }
    }
}